#pragma =======MarkVisitor.h=======
@class Dot, Vertex, Stroke
@protocol MarkVisitor <NSObject>

-(void) visitMark:(id<Mark>)mark;
-(void) visitDot:(Dot *)dot;
-(void) visitVertex:(Vertex*)vertex;
-(void) visitStroke:(Stroke*)stroke;

@end


#pragma =======MarkRenderer.h=======
#import "MarkVisitor.h"
#import "Dot.h"
#import "Vertex.h"
#import "Stroke.h"

@interface MarkRenderer : NSObject <MarkVisitor>{
    @private
    BOOL shouldMoveContextToDot_;
    @protected
    CGContextRef context_;
}
-(id)initWithCGContext:(CGContextRef)context;

-(void) visitMark:(id<Mark>)mark;
-(void) visitDot:(Dot *)dot;
-(void) visitVertex:(Vertex*)vertex;
-(void) visitStroke:(Stroke*)stroke;

@end


#pragma ==============MarkRenderer.m=======
#import "MarkRenderer.h"

@implementation MarkRenderer

-(id)initWithCGContext:(CGContextRef)context{
    if(self = [super init]) {
        context_ = context;
        shouldMoveContextToDot_ = YES;
    }
    return self;
}

-(void) visitMark:(id<Mark>)mark{
    //默认行为
}
@end


-(void) visitDot:(Dot *)dot{
    CGFloat x = [dot location].x;
    CGFloat y = [dot location].y;
    CGFloat frameSize = [dot size];
    CGRect frame = CGRectMake(x - frameSize / 2,
                              y - frameSize / 2,
                              frameSize,
                              frameSize);
    CGContextSetFillColorWithColor(context_, [[dot color] CGColor]);
    CGContextFillEllipseInRect(context_, frame);
}

-(void) visitVertex:(Vertex*)vertex{
    CGFloat x = [vertex location].x;
    CGFloat y = [vertex location].y;
    
    if(shouldMoveContextToDot_) {
        CGContextMoveToPoint(context_, x, y);
        shouldMoveContextToDot_ = NO;
    } else {s
        CGContextAddLineToPoint(context_, x, y);
    }
}

-(void) visitStroke:(Stroke*)stroke{
    CGContextSetStrokeColorWithColor(context_, [[stroke color] CGColor]);
    CGContextSetLineWidth(context_, [stroke size]);
    CGContextSetLineCap(context_, kCGLineCapRound);
    CGContextStrokePath(context_);
    shouldMoveContextToDot_ = YES;
}






#pragma =======Dot=======
-(void)acceptMarkVisitor:(id<MarkVisitor>)visitor{
    [visitor visitDot:self];
}

#pragma =======Vertex=======
-(void)acceptMarkVisitor:(id<MarkVisitor>)visitor{
    [visitor visitDot:self];
}

#pragma =======Stroke=======
-(void)acceptMarkVisitor:(id<MarkVisitor>)visitor{
    for(id <Mark> dot in children_){
        [dot acceptMarkVisitor(visitor)];
    }
    [visitor visitStroke:self];
}


